#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
#include <assert.h>

template<class T>
class my_vector
{
	using iterator = T*;
	using const_iterator = const T*;
private;
	iterator _start;
	iterator _finish;
	iterator _endofstorage;
public:
	iterator begin()
	{
		return _start;
	}
	iterator end()
	{
		return _finish;
	}
	size_t size()
	{
		return _finish - _start;
	}
	size_t capacity()
	{
		return _capacity - _start;
	}

	void swap(my_vector<T>& v)
	{
		std::swap(_start, v._start);
		std::swap(_finish, v._finish);
		std::swap(_endofstorage, v._endofstorage);
	}

	void reserve(size_t n)
	{
		if (n > capacity())
		{
			size_t old = size();
			T* tmp = new T[n];
			
			for (int i = 0; i < size(); i++)
				tmp[i] = _start[i];
			delete[] _start;
			_start = tmp;
			_finish = _start + old;
			_endofstorage = _start + n;
		}
	}

	void resize(size_t n,const T& val = T())
	{
		if (n <= size())
		{
			_finish = _start + n;
		}
		else
		{
			reserve(n);
			int begin = size();
			while (begin <= n)
			{
				_start[begin] = val;
				begin++;
			}
		}
	}
	my_vector()
		:_start(nullptr)
		,_finish(nullptr)
		,_endofstorage(nullptr)
	{}

	my_vector(size_t n, const T& val = T())
	{
		resize(n, val);
	}

	my_vector(const my_vector<T>& v)
	{
		reserve(v.capacity());
		for (auto& e : v)
		{
			push_back(e);
		}
	}
	my_vector(my_vector<T>&& v)
	{
		_start = v._start;
		_finish = v._finish;
		_endofstorage = v._endofstorage;

		v._start = nullptr;
		v._finish = nullptr;
		v._endofstorage = nullptr;

	}

	my_vector<T>& operator=(my_vector<T> v)
	{
		swap(v);
		return *this;
	}
	my_vector<T>& operator=(my_vector<T>&& v)
	{
		swap(v);
		return *this;
	}
	void push_back(const T& val)
	{
		if (_finish == _endofstorage)
		{
			size_t newcapacity = capacity() == 0 ? 4 : 1.5 * capacity();
			reserve(newcapacity);
		}
		*_finish = val;
		_finish++;
	}
	void pop_back()
	{
		assert(size());
		_finish--;
	}
	iterator insert(iterator pos, const T& val = T())
	{
		if (_finish == _endofstorage)
		{
			size_t newcapacity = capacity() == 0 ? 4 : 1.5 * capacity();
			size_t offset = pos - _start;
			reserve(newcapacity);
			pos = _start + offset;
		}
		iterator end = _finish - 1;
		while (end >= pos)
		{
			*(end + 1) = *end;
			end--;
		}
		*pos = val;
		_finish++;

		return pos;
	}

	iterator erase(iterator pos)
	{
		assert(pos >= 0 && pos < size());

		iterator begin = pos + 1;
		while (begin < _finish)
		{
			*(begin - 1) = *begin;
			begin++;
		}
		_finish--;
		
		return pos;
	}

	T& operator[](size_t pos)
	{
		assert(pos < size());

		return _start[pos];
	}
};